`include "defines.v"
`timescale 1ns / 1ps
`define SRC1_EXE_RELATIVE     		 ((exe2id_mreg == `TRUE_V) && (rreg1 == `TRUE_V) && (rs == exe2id_wa) && (exe2id_mreg ==`TRUE_V))
`define SRC1_MEM_RELATIVE 	      ((mem2id_mreg == `TRUE_V) && (rreg1 == `TRUE_V) && (rs == mem2id_wa) && (mem2id_mreg == `TRUE_V))
`define SRC2_EXE_RELATIVE  			 ((exe2id_mreg == `TRUE_V) && (rreg2 == `TRUE_V) && (rt == exe2id_wa) && (exe2id_mreg == `TRUE_V))
`define SRC2_MEM_RELATIVE         ((mem2id_mreg == `TRUE_V) && (rreg2 == `TRUE_V) && (rt == mem2id_wa) && (mem2id_mreg == `TRUE_V))

module DCU(
	inout  wire   													  cpu_rst_n,
	input wire [`REG_ADDR_BUS]							exe2id_wa,
	input wire														  exe2id_wreg,
	input wire                                                        exe2id_mreg,
	input wire [`REG_ADDR_BUS] 							mem2id_wa,
	input wire 														  mem2id_wreg,
	input wire                                                        mem2id_mreg,
	input wire[`REG_ADDR_BUS]  rs,
	input wire[`REG_ADDR_BUS] 	rt, 
	input wire[5:0]		op,
	input wire[5:0]		func,
	input wire  		  equ,

    output wire[7:0]               memtype,
	output wire[1:0] 				fwrd2,
	output wire[1:0]				fwrd1,
	output wire 		    	 	whilo,
	output wire						 wreg,
	output wire[2:0] 			alutype,
	output wire[7:0]		aluop,
	output wire 		shift,
	output wire	    	rreg1,
	output wire 		rreg2,
	output wire			immsel,
	output wire 		rtsel,
	output wire			sext,
	output wire 		upper,
	output wire 		mreg,
	output wire 		jal,
	output wire[1:0]  jtsel,
	output wire         stallreq_id 
);

wire 			inst_add_out;
wire            inst_addi_out;
wire            inst_addu_out;
wire            inst_addiu_out;
wire            inst_sub_out;
wire 			inst_subu_out;
wire 			inst_slt_out;
wire 			inst_slti_out;
wire			inst_sltu_out;
wire			inst_sltiu_out;
wire			inst_mult_out;
wire			inst_multu_out;
wire            inst_div_out;
wire  			inst_divu_out;
wire			inst_and_out;
wire 			inst_andi_out;
wire 			inst_lui_out;
wire 			inst_nor_out;
wire			inst_or_out;
wire 			inst_ori_out;
wire			inst_xor_out;
wire 			inst_xori_out;
wire 			inst_sll_out;
wire            inst_sllv_out;
wire            inst_sra_out;
wire            inst_srav_out;
wire            inst_srl_out;
wire            inst_srlv_out;
wire            inst_mfhi_out;
wire            inst_mflo_out;
wire            inst_mthi_out;
wire            inst_mtlo_out;
wire            inst_lb_out;
wire            inst_lbu_out;
wire            inst_lh_out;
wire            inst_lhu_out;
wire 			inst_lw_out;
wire 			inst_sb_out;
wire            inst_sh_out;
wire 			inst_sw_out;
wire 			inst_jal_out;
wire 			inst_j_out;
wire 			inst_jr_out;
wire 			inst_beq_out;
wire 			inst_bne_out;

DCU_step1 DCU_step10(
	.op         (op         ),
	.func       (func       ),
	.inst_add   (inst_add_out   ),
	.inst_addi  (inst_addi_out  ),
	.inst_addu  (inst_addu_out  ),
	.inst_addiu (inst_addiu_out ),
	.inst_sub   (inst_sub_out   ),
	.inst_subu  (inst_subu_out  ),
	.inst_slt   (inst_slt_out   ),
	.inst_slti  (inst_slti_out  ),
	.inst_sltu  (inst_sltu_out  ),
	.inst_sltiu (inst_sltiu_out ),
	.inst_mult  (inst_mult_out  ),
	.inst_multu (inst_multu_out ),
	.inst_div     (inst_div_out),
	.inst_divu   (inst_divu_out),
	.inst_and   (inst_and_out   ),
	.inst_andi  (inst_andi_out  ),
	.inst_lui   (inst_lui_out   ),
	.inst_nor   (inst_nor_out   ),
	.inst_or    (inst_or_out    ),
	.inst_ori   (inst_ori_out   ),
	.inst_xor   (inst_xor_out   ),
	.inst_xori  (inst_xori_out  ),
	.inst_sll   (inst_sll_out   ),
	.inst_sllv  (inst_sllv_out  ),
	.inst_sra   (inst_sra_out   ),
	.inst_srav  (inst_srav_out  ),
	.inst_srl   (inst_srl_out   ),
	.inst_srlv  (inst_srlv_out  ),
	.inst_mfhi  (inst_mfhi_out  ),
	.inst_mflo  (inst_mflo_out  ),
	.inst_mthi  (inst_mthi_out  ),
	.inst_mtlo  (inst_mtlo_out  ),
	.inst_lb    (inst_lb_out    ),
	.inst_lbu   (inst_lbu_out  ),
	.inst_lh    (inst_lh_out    ),
	.inst_lhu   (inst_lhu_out   ),
	.inst_lw    (inst_lw_out    ),
	.inst_sb    (inst_sb_out    ),
	.inst_sh    (inst_sh_out    ),
	.inst_sw    (inst_sw_out    ),
	.inst_jal   (inst_jal_out   ),
	.inst_j     (inst_j_out     ),
	.inst_jr    (inst_jr_out    ),
	.inst_beq   (inst_beq_out   ),
	.inst_bne   (inst_bne_out   )
);


DCU_step2 DCU_step20(
	.inst_add   (inst_add_out   ),
	.inst_addi  (inst_addi_out  ),
	.inst_addu  (inst_addu_out  ),
	.inst_addiu (inst_addiu_out ),
	.inst_sub   (inst_sub_out   ),
	.inst_subu  (inst_subu_out  ),
	.inst_slt   (inst_slt_out   ),
	.inst_slti  (inst_slti_out  ),
	.inst_sltu  (inst_sltu_out  ),
	.inst_sltiu (inst_sltiu_out ),
	.inst_mult  (inst_mult_out  ),
	.inst_multu (inst_multu_out ),
	.inst_div     (inst_div_out),
	.inst_divu   (inst_divu_out),
	.inst_and   (inst_and_out   ),
	.inst_andi  (inst_andi_out  ),
	.inst_lui   (inst_lui_out   ),
	.inst_nor   (inst_nor_out   ),
	.inst_or    (inst_or_out    ),
	.inst_ori   (inst_ori_out   ),
	.inst_xor   (inst_xor_out   ),
	.inst_xori  (inst_xori_out  ),
	.inst_sll   (inst_sll_out   ),
	.inst_sllv  (inst_sllv_out  ),
	.inst_sra   (inst_sra_out   ),
	.inst_srav  (inst_srav_out  ),
	.inst_srl   (inst_srl_out   ),
	.inst_srlv  (inst_srlv_out  ),
	.inst_mfhi  (inst_mfhi_out  ),
	.inst_mflo  (inst_mflo_out  ),
	.inst_mthi  (inst_mthi_out  ),
	.inst_mtlo  (inst_mtlo_out  ),
	.inst_lb    (inst_lb_out    ),
	.inst_lbu   (inst_lbu_out  ),
	.inst_lh    (inst_lh_out    ),
	.inst_lhu   (inst_lhu_out   ),
	.inst_lw    (inst_lw_out    ),
	.inst_sb    (inst_sb_out    ),
	.inst_sh    (inst_sh_out    ),
	.inst_sw    (inst_sw_out    ),
	.inst_jal   (inst_jal_out   ),
	.inst_j     (inst_j_out     ),
	.inst_jr    (inst_jr_out    ),
	.inst_beq   (inst_beq_out   ),
	.inst_bne   (inst_bne_out   ),
	.equ(equ),
    .whilo(whilo),
	.wreg(wreg),
	.alutype(alutype),
	.aluop(aluop),
    .shift(shift),
	.rreg1(rreg1),
	.rreg2(rreg2),
    .immsel(immsel),
    .rtsel(rtsel),
    .sext(sext),
    .upper(upper),
    .mreg(mreg),
	.jal(jal),
	.jtsel(jtsel)
	);
	//读寄存器端口1可能的数据来源
	assign fwrd1 = (exe2id_wreg == `WRITE_ENABLE  && exe2id_wa == rs && rreg1 == `READ_ENABLE  && exe2id_wa != 0 ) ? 2'b01:
							 (mem2id_wreg == `WRITE_ENABLE  && mem2id_wa == rs && rreg1 == `READ_ENABLE && mem2id_wa != 0 ) ? 2'b10:
							 (rreg1 == `READ_ENABLE) ?  2'b 11 : 2'b00;   
	assign fwrd2 = (exe2id_wreg == `WRITE_ENABLE  && exe2id_wa == rt && rreg2 == `READ_ENABLE && exe2id_wa != 0 ) ? 2'b01:
							 (mem2id_wreg == `WRITE_ENABLE  && mem2id_wa == rt && rreg2 == `READ_ENABLE && mem2id_wa != 0 ) ? 2'b10:
							 (rreg2 == `READ_ENABLE) ?  2'b 11 : 2'b00;   

	assign stallreq_id = (cpu_rst_n == `RST_ENABLE) ?  `PIPELINE_NOSTOP :
									 (`SRC1_EXE_RELATIVE || `SRC1_MEM_RELATIVE || `SRC2_EXE_RELATIVE || `SRC2_MEM_RELATIVE) ? 
									 `PIPELINE_STOP : `PIPELINE_NOSTOP;
	assign memtype = { inst_sw_out,inst_sh_out,inst_sb_out,inst_lw_out,inst_lhu_out,inst_lh_out,inst_lbu_out,inst_lb_out };
	
endmodule	
